function gadget:GetInfo()
	return {
	name      = "Turret Handler",
	desc      = "Handles Everything For turrets",
	author    = "SkyStar",
	date      = "2010", 
	license   = "GNU GPL, v2 or later",
	layer     = 1, --lowest go first
	enabled   = true, --loaded by default
	}
end
	
if (gadgetHandler:IsSyncedCode()) then		
--------------------------------------
--------------- SYNCED ---------------
--------------------------------------
local turrets = {}
local basePos = {}
--------------------------------------

	function gadget:Initialize() -- Everything as soon as Gadget loads
	-- Prepare Global Framework functions --
	Gfunction = _G.functions
	luaAIAllyID = Gfunction.getLuaAIAllies()
	security =  Gfunction.secureNum()	
	end -- Initialize()
	
	function gadget:UnitCreated(unitID,unitDefID,unitTeam) -- Handle stuff that spawns
		if Gfunction.getUnitDef(unitID).name == "turreta"then
		local _,_,_,_,_,allyID = Spring.GetTeamInfo(unitTeam)
		local AIAlly = Gfunction.getLuaAIAllies()
		-- Change the turrets so they are AI --
		Spring.TransferUnit(unitID,AIAlly[allyID],false)
		local x,y,z = Spring.GetUnitPosition(unitID)
		-- Start them falling -- 
		Spring.MoveCtrl.Enable(unitID)
		Spring.MoveCtrl.SetPosition(unitID, x, y + 4000,z )
		Spring.MoveCtrl.SetGravity(unitID, 10)
		turrets[unitID] = true
		Spring.PlaySoundFile("turretfall")
		end
	end -- UnitCreated()

	function gadget:RecvLuaMsg(msg, playerID)
		if string.find(msg, "getSecure") then
		SendToUnsynced("security", security) -- Send to unsynced, this is local I think so it can't be grabbed by a widget
		end
	end


	function gadget:GameFrame(frame) -- Stuff to do while game is running but not paused
		for unitID in pairs(turrets) do
		local x,y,z = Spring.GetUnitPosition(unitID)
		local h = Spring.GetGroundHeight(x, z)
			if y+20 <= h then		
			-- If were gonna hit the ground do the effect -- 
			Spring.MoveCtrl.SetGravity(unitID, 0)
			Spring.MoveCtrl.SetVelocity(unitID,0,0,0)
			Spring.SetUnitPosition(unitID,x,h,z)
			turrets[unitID] = nil
			Spring.SpawnCEG("Smash Ground", x, h, z)
			Spring.PlaySoundFile("turretland")
			elseif y > h + 100 then
			-- If were in the air do the effect -- 
			local x,y,z = Spring.GetUnitPosition(unitID)
			Spring.SpawnCEG("Burn Fall", x, y, z)
			end
		end
	end	
end -- SYNCED

if (not gadgetHandler:IsSyncedCode()) then	

-----------------------------------
---------- UN-SYNCED --------------
-----------------------------------
local validate = 0

local glColor = gl.Color
local glRect = gl.Rect
local glTexture = gl.Texture
local glTexRect = gl.TexRect

local buttonTex = "#" .. UnitDefNames.turreta.id
local wl, wt = 200, 200
local buttonWidth = 50
local buttonHeight = 50
local buttonBorderSize = 2
	
local isDragging = false	
local isSelected = false	
local isAllowed = false	
	
local localAllyID = Spring.GetLocalAllyTeamID()	
local localTeamID = Spring.GetLocalTeamID()	
local gaiaAllyID	
	
local turretList = {}	
----------------------------------

	local function security(_,number)
	validate = number
	end
	
	function gadget:Initialize() -- Stuff to start when gadget loads
	local teams = Spring.GetTeamList()	
	for i = 1,#teams do
	local teamID = teams[i]
		_,_,_,_,_,gaiaAllyID = Spring.GetTeamInfo(teamID)
	end	
	gadgetHandler:AddSyncAction("security", security)
	Spring.SendLuaRulesMsg("getSecure")
	end -- Initialize()



	function gadget:IsAbove(mx, my) -- Not sure what this is for really, everyone uses it so why not?
	-- Is the mouse over the button? --
	return (mx >= wl) and (mx <= wl + buttonWidth) and (my <= wt) and (my >= wt - buttonHeight)
	end -- IsAbove()
	
	function gadget:MousePress(mx, my, mButton) -- Everything about using the mouse buttons
	-- Set up the turret counter --
		if not turretList[localTeamID] then
		turretList[localTeamID] = 2
		end
	-- Stop everything if we have spawned 2 turrets	
		if turretList[localTeamID] < 1 then return end
	-- If we have already selected the turret then send command to spawn turret --	
		if isSelected == true and mButton == 1 then
		local mx, my = Spring.GetMouseState()
		local _, pos = Spring.TraceScreenRay(mx, my, true)
			if pos then
			local bx, by, bz = Spring.Pos2BuildPos(UnitDefNames.turreta.id, pos[1], pos[2], pos[3])
			local blocking = false
			-- We can't be too close to enemy base or inside enemy start box now can we? --
				if isAllowed then
				Spring.SendLuaRulesMsg("Gfunction:"..'createTurret'..','..bx..','..by..','..bz..','..localAllyID..','..validate)
				turretList[localTeamID] = turretList[localTeamID] - 1
				isSelected = false
				return true
				end
			end
		end	
	-- If we right click while selected then cancel --
		if mButton == 3 and not gadget:IsAbove(mx, my) then
		isSelected = false
		return true
		end
	-- If we are not above the turret button then we obviously can't use it --
		if not gadget:IsAbove(mx, my) then return false end
	-- If we have clicked the turret button then select the turret --	
		if mButton == 1 and isSelected == false then
		isSelected = true
		return true
		end
	-- If we right clicked on the turret button prepare to move the turret button --
		if mButton == 3 then
		isDragging = true
		return true
		end
	end -- MousePress()
	
	function gadget:MouseRelease(mx, my, mButton) -- If we let go of the right mouse button stop moving the button
	isDragging = false
	end -- MouseRelease()
	
	function gadget:MouseMove(mx, my, dx, dy, mButton) -- If we are holding the right mouse button then move the turret button
		if isDragging then		
		wl = wl + dx
		wt = wt + dy
		end
	end -- MouseMove()
	
	function gadget:DrawScreen() -- Draw the button
	-- Don't show button if we cannot build more --
		if turretList[localTeamID] and turretList[localTeamID] < 1 then return end
	-- Don't show button before game start --
		if Spring.GetGameFrame() == 0 then return end 
	-- Draw the button --
	glColor(0, 0, 0, 1)
	glRect(wl - buttonBorderSize, wt + buttonBorderSize, wl + buttonWidth + buttonBorderSize, wt - buttonHeight - buttonBorderSize)	-- Button Border (black)
	glColor(1, 1, 1, 1)	
	glTexture(buttonTex)
	glTexRect(wl, wt - buttonHeight, wl + buttonWidth, wt) -- Button Image (turretA)
	glTexture(false)	
	end -- DrawScreen()
	
	function gadget:DrawWorld()	-- If the turret is selected and is waiting for placement draw a ghosted turret
	-- Don't Show ghost if we cannot build more
	if turretList[localTeamID] and turretList[localTeamID] < 1 then return end
		if isSelected then 
		local mx, my = Spring.GetMouseState()
		local _, pos = Spring.TraceScreenRay(mx, my, true)
			if pos then
				local bx, by, bz = Spring.Pos2BuildPos(UnitDefNames.turreta.id, pos[1], pos[2], pos[3])
				gl.Color(1.0, 1.0, 1.0, 1.0)
				gl.DepthTest(GL.LEQUAL)
				gl.DepthMask(true)
				gl.Lighting(true)
				
				gl.PushMatrix()
				gl.Translate(bx, by, bz)
				gl.UnitShape(UnitDefNames.turreta.id, localTeamID)
				gl.PopMatrix()
				
				gl.Lighting(false)
				gl.DepthTest(false)
				gl.DepthMask(false)
				
				local bw, bh = GetBuildingDimensions(UnitDefNames.turreta.id, Spring.GetBuildFacing())
	
				gl.DepthTest(false)
				if spawnAllowed(bx,bz) then
				gl.Color(0,1,0,1)
				isAllowed = true
				else
				gl.Color(1,0,0,1)
				isAllowed = false
				end
				gl.LineWidth(5)
				gl.Shape(GL.LINE_LOOP, {{v={bx - bw, by, bz - bh}},
										{v={bx + bw, by, bz - bh}},
										{v={bx + bw, by, bz + bh}},
										{v={bx - bw, by, bz + bh}}})
			end
		end
	end -- DrawWorld()
	
	function GetBuildingDimensions(uDefID, facing) -- Get the building size
	local bDef = UnitDefs[uDefID]
		if (facing % 2 == 1) then
		return 4 * bDef.zsize, 4 * bDef.xsize
		else
		return 4 * bDef.xsize, 4 * bDef.zsize
		end
	end -- GetBuildingDimensions()
	
	function spawnAllowed(x,z) -- Find out if we can spawn a turret here
		-- We cannot spawn too close to enemy box --
		local Allies = Spring.GetAllyTeamList()		
		for i = 1,#Allies do
		local allyID = Allies[i]
			if (localAllyID ~= allyID and allyID ~= gaiaAllyID) then
			local xmin, zmin, xmax, zmax = Spring.GetAllyTeamStartBox(allyID)
			local xdif = xmax - xmin
			local zdif = zmax - zmin
			local mapX = math.floor(Game.mapSizeX)
			local mapZ = math.floor(Game.mapSizeZ)
			local boxDouble = (xdif * zdif) * 2
			local mapSqrd = mapX * mapZ
				if(xmax and xmin) then
				local mapDist = (mapSqrd - boxDouble) / 10
					if mapDist < 0 then
					mapDist = 0
					end
				-- Cannot be inside enemy start box --
					if(x < xmax and x > xmin and z < zmax and z > zmin) then
					return false
					end
				-- Cannot be near enemy start box --
					if((x-xmin)^2 + (z-zmin)^2 < mapDist) then
					return false
					end
					if((x-xmax)^2 + (z-zmax)^2 < mapDist) then
					return false
					end
					if((x-xmax)^2 + (z-zmin)^2 < mapDist) then
					return false
					end
					if((x-xmin)^2 + (z-zmax)^2 < mapDist) then
					return false
					end	
										
					if((x-xmin)^2 + (z-(zmin+zdif*0.1))^2 < mapDist) then
					return false
					end
					if((x-xmax)^2 + (z-(zmax-zdif*0.1))^2 < mapDist) then
					return false
					end
					if((x-(xmax-xdif*0.1))^2 + (z-zmin)^2 < mapDist) then
					return false
					end
					if((x-(xmin+xdif*0.1))^2 + (z-zmax)^2 < mapDist) then
					return false
					end
					
					if((x-xmin)^2 + (z-(zmin+zdif*0.2))^2 < mapDist) then
					return false
					end
					if((x-xmax)^2 + (z-(zmax-zdif*0.2))^2 < mapDist) then
					return false
					end
					if((x-(xmax-xdif*0.2))^2 + (z-zmin)^2 < mapDist) then
					return false
					end
					if((x-(xmin+xdif*0.2))^2 + (z-zmax)^2 < mapDist) then
					return false
					end
					
					if((x-xmin)^2 + (z-(zmin+zdif*0.4))^2 < mapDist) then
					return false
					end
					if((x-xmax)^2 + (z-(zmax-zdif*0.4))^2 < mapDist) then
					return false
					end
					if((x-(xmax-xdif*0.4))^2 + (z-zmin)^2 < mapDist) then
					return false
					end
					if((x-(xmin+xdif*0.4))^2 + (z-zmax)^2 < mapDist) then
					return false
					end		
					
					if((x-xmin)^2 + (z-(zmin+zdif*0.5))^2 < mapDist) then
					return false
					end
					if((x-xmax)^2 + (z-(zmax-zdif*0.5))^2 < mapDist) then
					return false
					end
					if((x-(xmax-xdif*0.5))^2 + (z-zmin)^2 < mapDist) then
					return false
					end
					if((x-(xmin+xdif*0.5))^2 + (z-zmax)^2 < mapDist) then
					return false
					end	
					
					if((x-xmin)^2 + (z-(zmin+zdif*0.6))^2 < mapDist) then
					return false
					end
					if((x-xmax)^2 + (z-(zmax-zdif*0.6))^2 < mapDist) then
					return false
					end
					if((x-(xmax-xdif*0.6))^2 + (z-zmin)^2 < mapDist) then
					return false
					end
					if((x-(xmin+xdif*0.6))^2 + (z-zmax)^2 < mapDist) then
					return false
					end
					
					if((x-xmin)^2 + (z-(zmin+zdif*0.7))^2 < mapDist) then
					return false
					end
					if((x-xmax)^2 + (z-(zmax-zdif*0.7))^2 < mapDist) then
					return false
					end
					if((x-(xmax-xdif*0.7))^2 + (z-zmin)^2 < mapDist) then
					return false
					end
					if((x-(xmin+xdif*0.7))^2 + (z-zmax)^2 < mapDist) then
					return false
					end
					
					if((x-xmin)^2 + (z-(zmin+zdif*0.8))^2 < mapDist) then
					return false
					end
					if((x-xmax)^2 + (z-(zmax-zdif*0.8))^2 < mapDist) then
					return false
					end
					if((x-(xmax-xdif*0.8))^2 + (z-zmin)^2 < mapDist) then
					return false
					end
					if((x-(xmin+xdif*0.8))^2 + (z-zmax)^2 < mapDist) then
					return false
					end
					
					if((x-xmin)^2 + (z-(zmin+zdif*0.9))^2 < mapDist) then
					return false
					end
					if((x-xmax)^2 + (z-(zmax-zdif*0.9))^2 < mapDist) then
					return false
					end
					if((x-(xmax-xdif*0.9))^2 + (z-zmin)^2 < mapDist) then
					return false
					end
					if((x-(xmin+xdif*0.9))^2 + (z-zmax)^2 < mapDist) then
					return false
					end

				end
			end
		end
	return true	
	end -- spawnAllowed
end -- UnSynced

